package com.zk.cq.config;

import com.alibaba.fastjson.JSON;
import com.zk.cq.annotation.Listener;
import com.zk.cq.annotation.RobotListeners;
import com.zk.cq.constant.ListenerContext;
import com.zk.cq.constant.PostTypes;
import com.zk.cq.model.bo.BeanMethodBO;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class RobotListenerScan implements ApplicationListener<ContextRefreshedEvent> {
    private final static Logger logger = LoggerFactory.getLogger(RobotListenerScan.class);
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if(event.getApplicationContext().getParent() == null){
            Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(RobotListeners.class);
            logger.info(">>>RobotListenerScan>>>start");

            for (Object bean:beans.values()){
                RobotListeners classAn = bean.getClass().getAnnotation(RobotListeners.class);
                logger.info(":::Class=" + bean.getClass().getSimpleName() + "  :::PostType=" + classAn.postType() );
                initListenerContext(classAn,bean);
            }
            logger.info("ListenerContext==" + JSON.toJSONString(ListenerContext.POST_TYPE_CONTEXT));
            logger.info(">>>RobotListenerScan>>>end");
        }
    }

    private void initListenerContext(RobotListeners classAn, Object bean){
        if (PostTypes.MESSAGE.equals(classAn.postType())){
            Map<String, List<BeanMethodBO>> message = ListenerContext.POST_TYPE_CONTEXT.get(PostTypes.MESSAGE);
            Method[] methods = bean.getClass().getDeclaredMethods();
            for (Method method:methods){
                Listener listenerV = method.getAnnotation(Listener.class);
                if (listenerV == null){
                    continue;
                }
                switch (listenerV.value()){
                    case PostTypes.MessageType.PRIVATE:
                        message.get(PostTypes.MessageType.PRIVATE).add(new BeanMethodBO(bean,method));
                        break;
                    case PostTypes.MessageType.GROUP:
                        message.get(PostTypes.MessageType.GROUP).add(new BeanMethodBO(bean,method));
                        break;
                    case PostTypes.MessageType.DISCUSS:
                        message.get(PostTypes.MessageType.DISCUSS).add(new BeanMethodBO(bean,method));
                        break;
                    default:
                        log.info("@Listener value 不存在请检查：" + listenerV);
                        throw new RuntimeException("@Listener value 不存在请检查：" + listenerV);
                }
            }
        }else if (PostTypes.NOTICE.equals(classAn.postType())){
            Map<String, List<BeanMethodBO>> message = ListenerContext.POST_TYPE_CONTEXT.get(PostTypes.NOTICE);
            Method[] methods = bean.getClass().getDeclaredMethods();
            for (Method method:methods){
                Listener listenerV = method.getAnnotation(Listener.class);
                if (listenerV == null){
                    continue;
                }
                switch (listenerV.value()){
                    case PostTypes.NoticeType.GROUP_UPLOAD:
                        message.get(PostTypes.NoticeType.GROUP_UPLOAD).add(new BeanMethodBO(bean,method));
                        break;
                    case PostTypes.NoticeType.GROUP_ADMIN:
                        message.get(PostTypes.NoticeType.GROUP_ADMIN).add(new BeanMethodBO(bean,method));
                        break;
                    case PostTypes.NoticeType.GROUP_DECREASE:
                        message.get(PostTypes.NoticeType.GROUP_DECREASE).add(new BeanMethodBO(bean,method));
                        break;
                    case PostTypes.NoticeType.GROUP_INCREASE:
                        message.get(PostTypes.NoticeType.GROUP_INCREASE).add(new BeanMethodBO(bean,method));
                        break;
                    case PostTypes.NoticeType.FRIEND_ADD:
                        message.get(PostTypes.NoticeType.FRIEND_ADD).add(new BeanMethodBO(bean,method));
                        break;
                    default:
                        log.info("@Listener value 不存在请检查：" + listenerV);
                        throw new RuntimeException("@Listener value 不存在请检查：" + listenerV);
                }
            }
        }else if (PostTypes.REQUEST.equals(classAn.postType())){
            Map<String, List<BeanMethodBO>> message = ListenerContext.POST_TYPE_CONTEXT.get(PostTypes.REQUEST);
            Method[] methods = bean.getClass().getDeclaredMethods();
            for (Method method:methods){
                Listener listenerV = method.getAnnotation(Listener.class);
                if (listenerV == null){
                    continue;
                }
                switch (listenerV.value()){
                    case PostTypes.RequestType.FRIEND:
                        message.get(PostTypes.RequestType.FRIEND).add(new BeanMethodBO(bean,method));
                        break;
                    case PostTypes.RequestType.GROUP:
                        message.get(PostTypes.RequestType.GROUP).add(new BeanMethodBO(bean,method));
                        break;
                    default:
                        log.info("@Listener value 不存在请检查：" + listenerV);
                        throw new RuntimeException("@Listener value 不存在请检查：" + listenerV);
                }
            }
        }else if (PostTypes.META_EVENT.equals(classAn.postType())){
            Map<String, List<BeanMethodBO>> message = ListenerContext.POST_TYPE_CONTEXT.get(PostTypes.META_EVENT);
            Method[] methods = bean.getClass().getDeclaredMethods();
            for (Method method:methods){
                Listener listenerV = method.getAnnotation(Listener.class);
                if (listenerV == null){
                    continue;
                }
                switch (listenerV.value()){
                    case PostTypes.MetaEventType.LIFECYCLE:
                        message.get(PostTypes.MetaEventType.LIFECYCLE).add(new BeanMethodBO(bean,method));
                        break;
                    case PostTypes.MetaEventType.HEARTBEAT:
                        message.get(PostTypes.MetaEventType.HEARTBEAT).add(new BeanMethodBO(bean,method));
                        break;
                    default:
                        log.info("@Listener value 不存在请检查：" + listenerV);
                        throw new RuntimeException("@Listener value 不存在请检查：" + listenerV);
                }
            }
        }
    }
}

